﻿using Microsoft.EntityFrameworkCore;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.BackgroundJobs.EntityFrameworkCore;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.OpenIddict.EntityFrameworkCore;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
using CKY.AgentPlatform.Agents;
using CKY.AgentPlatform.ModelConfigs;
using CKY.AgentPlatform.Conversations;
using CKY.AgentPlatform.PromptTemplates;
using CKY.AgentPlatform.Domain.McpTools;
using CKY.AgentPlatform.Mcp;

namespace CKY.AgentPlatform.EntityFrameworkCore;

[ReplaceDbContext(typeof(IIdentityDbContext))]
[ReplaceDbContext(typeof(ITenantManagementDbContext))]
[ConnectionStringName("Default")]
public class AgentPlatformDbContext :
    AbpDbContext<AgentPlatformDbContext>,
    IIdentityDbContext,
    ITenantManagementDbContext,
    IAgentPlatformDbContext
{
    /* Add DbSet properties for your Aggregate Roots / Entities here. */

    #region Entities from the modules

    /* Notice: We only implemented IIdentityDbContext and ITenantManagementDbContext
     * and replaced them for this DbContext. This allows you to perform JOIN
     * queries for the entities of these modules over the repositories easily. You
     * typically don't need that for other modules. But, if you need, you can
     * implement the DbContext interface of the needed module and use ReplaceDbContext
     * attribute just like IIdentityDbContext and ITenantManagementDbContext.
     *
     * More info: Replacing a DbContext of a module ensures that the related module
     * uses this DbContext on runtime. Otherwise, it will use its own DbContext class.
     */

    //Identity
    public DbSet<IdentityUser> Users { get; set; }
    public DbSet<IdentityRole> Roles { get; set; }
    public DbSet<IdentityClaimType> ClaimTypes { get; set; }
    public DbSet<OrganizationUnit> OrganizationUnits { get; set; }
    public DbSet<IdentitySecurityLog> SecurityLogs { get; set; }
    public DbSet<IdentityLinkUser> LinkUsers { get; set; }
    public DbSet<IdentityUserDelegation> UserDelegations { get; set; }
    public DbSet<IdentitySession> Sessions { get; set; }
    // Tenant Management
    public DbSet<Tenant> Tenants { get; set; }
    public DbSet<TenantConnectionString> TenantConnectionStrings { get; set; }
    
    // Custom Business Entities
    public DbSet<Agents.Agent> Agents { get; set; }
    public DbSet<ModelConfigs.ModelConfig> ModelConfigs { get; set; }
    public DbSet<Conversations.Conversation> Conversations { get; set; }
    public DbSet<Conversations.ConversationMessage> ConversationMessages { get; set; }
    public DbSet<PromptTemplates.PromptTemplate> PromptTemplates { get; set; }
    public DbSet<CKY.AgentPlatform.Domain.McpTools.McpTool> McpTools { get; set; }
    public DbSet<CKY.AgentPlatform.Mcp.McpServer> McpServers { get; set; }

    #endregion

    public AgentPlatformDbContext(DbContextOptions<AgentPlatformDbContext> options)
        : base(options)
    {

    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        /* Configure SQLite specific mappings */
        if (Database.IsSqlite())
        {
            foreach (var entityType in builder.Model.GetEntityTypes())
            {
                foreach (var property in entityType.GetProperties())
                {
                    if (property.GetColumnType() == "nvarchar(max)" ||
                        property.GetColumnName() == "ExtraProperties" ||
                        property.GetColumnName() == "Exceptions")
                    {
                        property.SetColumnType("TEXT");
                    }
                }
            }
        }

        /* Include modules to your migration db context */

        builder.ConfigurePermissionManagement();
        builder.ConfigureSettingManagement();
        builder.ConfigureBackgroundJobs();
        builder.ConfigureAuditLogging();
        builder.ConfigureIdentity();
        builder.ConfigureOpenIddict();
        builder.ConfigureFeatureManagement();
        builder.ConfigureTenantManagement();

        /* Configure your own tables/entities inside here */

        // Configure MCP entities
        builder.ConfigureMcp();

        // Configure Agent entity
        builder.Entity<Agents.Agent>(b =>
        {
            b.ToTable(AgentPlatformConsts.DbTablePrefix + "Agents", AgentPlatformConsts.DbSchema);
            // b.ConfigureByConvention(); // 暂时注释掉，避免编译错误
            
            b.Property(a => a.Name).IsRequired().HasMaxLength(200);
            b.Property(a => a.Description).HasMaxLength(1000);
            b.Property(a => a.SystemPrompt).IsRequired();
            b.Property(a => a.Configuration).HasColumnType("TEXT");
            b.Property(a => a.Tags).HasMaxLength(500);
            
            b.HasOne<ModelConfigs.ModelConfig>()
                .WithMany()
                .HasForeignKey(a => a.ModelConfigId)
                .OnDelete(DeleteBehavior.Restrict);
                
            b.HasOne<PromptTemplates.PromptTemplate>()
                .WithMany()
                .HasForeignKey(a => a.PromptTemplateId)
                .OnDelete(DeleteBehavior.SetNull);
        });

        // Configure ModelConfig entity
        builder.Entity<ModelConfigs.ModelConfig>(b =>
        {
            b.ToTable(AgentPlatformConsts.DbTablePrefix + "ModelConfigs", AgentPlatformConsts.DbSchema);
            // b.ConfigureByConvention(); // 暂时注释掉，避免编译错误

            b.Property(m => m.Name).IsRequired().HasMaxLength(200);
            b.Property(m => m.Description).HasMaxLength(1000);
            b.Property(m => m.Model).IsRequired().HasMaxLength(100);
            b.Property(m => m.ApiKey).IsRequired().HasMaxLength(500);
            b.Property(m => m.ApiBaseUrl).HasMaxLength(500);
            b.Property(m => m.ProxySettings).HasMaxLength(1000);
            b.Property(m => m.CustomParameters).HasColumnType("TEXT");
            b.Property(m => m.AdditionalConfig)
                .HasColumnType("TEXT")
                .HasConversion(
                    v => System.Text.Json.JsonSerializer.Serialize(v, (System.Text.Json.JsonSerializerOptions)null),
                    v => System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(v, (System.Text.Json.JsonSerializerOptions)null)
                );
            b.Property(m => m.TotalResponseTimeMs).HasDefaultValue(0L);
        });

        // Configure Conversation entity
        builder.Entity<Conversations.Conversation>(b =>
        {
            b.ToTable(AgentPlatformConsts.DbTablePrefix + "Conversations", AgentPlatformConsts.DbSchema);
            // b.ConfigureByConvention(); // 暂时注释掉，避免编译错误
            
            b.Property(c => c.Title).IsRequired().HasMaxLength(300);
            b.Property(c => c.SystemPrompt).HasMaxLength(4000);
            b.Property(c => c.Tags).HasMaxLength(500);
            b.Property(c => c.SessionId).IsRequired().HasMaxLength(100);
            b.Property(c => c.Summary).HasMaxLength(2000);
            b.Property(c => c.Feedback).HasMaxLength(2000);
            b.Property(c => c.Metadata).HasColumnType("TEXT");
            
            b.HasOne<Agents.Agent>()
                .WithMany()
                .HasForeignKey(c => c.AgentId)
                .OnDelete(DeleteBehavior.Cascade);
                
            b.HasIndex(c => c.SessionId);
            b.HasIndex(c => c.StartTime);
            b.HasIndex(c => c.Status);
        });

        // Configure ConversationMessage entity
        builder.Entity<Conversations.ConversationMessage>(b =>
        {
            b.ToTable(AgentPlatformConsts.DbTablePrefix + "ConversationMessages", AgentPlatformConsts.DbSchema);
            // b.ConfigureByConvention(); // 暂时注释掉，避免编译错误
            
            b.Property(m => m.Content).IsRequired();
            b.Property(m => m.ErrorMessage).HasMaxLength(2000);
            b.Property(m => m.Metadata).HasColumnType("TEXT");
            
            b.HasOne<Conversations.Conversation>()
                .WithMany(c => c.Messages)
                .HasForeignKey(m => m.ConversationId)
                .OnDelete(DeleteBehavior.Cascade);
                
            b.HasIndex(m => m.ConversationId);
            b.HasIndex(m => m.Order);
        });

        // Configure PromptTemplate entity
        builder.Entity<PromptTemplates.PromptTemplate>(b =>
        {
            b.ToTable(AgentPlatformConsts.DbTablePrefix + "PromptTemplates", AgentPlatformConsts.DbSchema);
            // b.ConfigureByConvention(); // 暂时注释掉，避免编译错误
            
            b.Property(p => p.Name).IsRequired().HasMaxLength(200);
            b.Property(p => p.Description).HasMaxLength(1000);
            b.Property(p => p.Template).IsRequired();
            b.Property(p => p.Tags).HasMaxLength(500);
            b.Property(p => p.Parameters).HasColumnType("TEXT");
            b.Property(p => p.Examples).HasColumnType("TEXT");
            b.Property(p => p.Metadata).HasColumnType("TEXT");
            
            b.HasOne<PromptTemplates.PromptTemplate>()
                .WithMany(p => p.ChildTemplates)
                .HasForeignKey(p => p.ParentTemplateId)
                .OnDelete(DeleteBehavior.SetNull);
                
            b.HasIndex(p => p.Category);
            b.HasIndex(p => p.IsSystem);
        });

        // Configure McpTool entity
        builder.Entity<CKY.AgentPlatform.Domain.McpTools.McpTool>(b =>
        {
            b.ToTable(AgentPlatformConsts.DbTablePrefix + "McpTools", AgentPlatformConsts.DbSchema);
            // b.ConfigureByConvention(); // 暂时注释掉，避免编译错误
            
            b.Property(t => t.Name).IsRequired().HasMaxLength(200);
            b.Property(t => t.Description).HasMaxLength(1000);
            b.Property(t => t.Version).HasMaxLength(50);
            b.Property(t => t.Command).IsRequired();
            b.Property(t => t.Configuration).HasColumnType("TEXT");
            b.Property(t => t.Parameters).HasColumnType("TEXT");
            b.Property(t => t.ReturnFormat).HasColumnType("TEXT");
            b.Property(t => t.RequiredPermissions).HasMaxLength(1000);
            b.Property(t => t.Tags).HasMaxLength(500);
            b.Property(t => t.Author).HasMaxLength(200);
            b.Property(t => t.DocumentationUrl).HasMaxLength(1000);
            b.Property(t => t.Metadata).HasColumnType("TEXT");
            
            b.HasIndex(t => t.ToolType);
            b.HasIndex(t => t.Status);
            b.HasIndex(t => t.IsActive);
        });
    }

    // Database 属性已在基类 DbContext 中定义，无需重复定义
}
